﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using DatabaseInterface.DataBase;
using System.Data;

namespace BaseUnits
{
    public class PowerUnit : IPowerUnit
    {
        int powerUnitId;
        String description;
        String externalId;
        DateTime buildDate;
        PowerUnits.PowerUnitPriorityDataTable priorityTable;
        PowerUnits.EmissionFactorsDataTable emissionFactor;
        PowerUnits.ProductionDataTable production;
        Boolean isCDM;

        public PowerUnit(int powerUnitId, String description, String externalId, DateTime buildDate, PowerUnits.PowerUnitPriorityDataTable priorityTable, PowerUnits.EmissionFactorsDataTable emissionFactor, PowerUnits.ProductionDataTable production, Boolean isCDM)
        {
            this.powerUnitId = powerUnitId;
            this.description = description;
            this.buildDate = buildDate;
            this.isCDM = isCDM;
            this.externalId = externalId;
            this.priorityTable = priorityTable;
            this.emissionFactor = emissionFactor;
            this.production = production;
        }
        public String ExternalId
        {
            set { this.externalId = value; }
            get { return this.externalId; }
        }
        public int ID
        {
            set { this.powerUnitId = value; }
            get { return this.powerUnitId; }
        }
        public String Description
        {
            set { this.description = value; }
            get { return this.description; }
        }
        public DateTime BuildDate
        {
            get { return this.buildDate; }
        }

        public int Priority(DateTime date, int hour)
        {
            //DateTime date = new DateTime(year, 1, 1);
            //date = date.AddHours(hour);
            String filter = "Date < '" + date.ToShortDateString() + "'";
            if (hour != -1)
            {
                filter += " OR (Date = '" + date.ToShortDateString() + "' AND hour <= " + hour + ")";
            }
            else
            {
                filter += " OR (Date = '" + date.ToShortDateString() + "' AND  hour <= " + (date.Hour + 1) + ")";
            }
            System.Data.DataRow[] rows = this.priorityTable.Select(filter);

            rows.OrderByDescending(row => row["Priority"]);
                return (int)rows[0]["Priority"];
        }

        public double EmissionFactor(DateTime date, int hour = -1)
        {
            double emissionFactor = 0;
            if (hour != -1)
            {
                date.AddHours(hour);
            }
            //DateTime date = new DateTime(year, 1, 1);
            //date = date.AddHours(hour);
            //String filter = "Date = " + date.ToShortDateString();
            //filter += " AND hour = " + date.Hour;
            //System.Data.DataRow[] rows = this.production.Select(filter);
            //System.Data.DataRow[] rows = this.emissionFactor.Select(filter);

            IEnumerable<DataRow> emission = from emF in this.emissionFactor
                                            where emF.Date <= date
                                            orderby emF.Date descending
                                            select emF;

            if (emission.Count<DataRow>() != 0)
            {
                emissionFactor = Convert.ToDouble(emission.ElementAt<DataRow>(0)["Factor"].ToString());
            }
            return emissionFactor;
        }

        public double FuelConsumption(DateTime date, int hour = -1)
        {
            double fuelConsumption = -1;
            //DateTime date = new DateTime(year, 1, 1);
            if (hour != -1)
            {
                date = date.AddHours(hour);
            }
            IEnumerable<PowerUnits.ProductionRow> fuelConsumptionRows;
            fuelConsumptionRows = from fc in this.production
                                  where fc.Date == date
                                  select fc;
            if (fuelConsumptionRows.Count<PowerUnits.ProductionRow>() != 0)
            {
                if (fuelConsumptionRows.ElementAt(0)["FuelQuantity"] != null)
                {
                    fuelConsumption = fuelConsumptionRows.ElementAt(0).FuelQuantity;
                }
            }
            return fuelConsumption;
        }
        public Boolean IsCDM
        {
            get { return this.isCDM; }
        }
        public override string ToString()
        {
            return this.Description;
        }
        public IPowerPlant GetPowerPlant()
        {
            BaseUnits.Builders.PowerPlantBuilder powerPlantBuilder = new Builders.PowerPlantBuilder(new DatabaseInterface.Connection());
            return powerPlantBuilder.getPowerPlant(this);
        }
        /// <summary>
        /// Electricity dispatch of power unit
        /// </summary>
        /// <param name="year">year of dispatch</param>
        /// <param name="hour">hour of dispatch. If -1 gets total year dispatch</param>
        /// <returns></returns>
        public double ElectricityDispatch(DateTime date, int hour = -1)
        {
            //if (hour != -1)
            //{
            //    date.AddHours(hour);
                
            //}
            ////DateTime date = ConvertHourToDate(year, hour);
            //String filter = "Date = '" + date.ToShortDateString() + "'";
            //filter += " AND hour = " + (date.Hour + 1);
            //System.Data.DataRow[] rows = this.production.Select(filter);

            //double outgoing = (double)rows[0]["Outgoing"];
            //double incoming = (double)rows[0]["Incoming"];
            double outgoing = GetOutgoing(date);
            double incoming = GetIncoming(date);

            return  outgoing - incoming;
        }
        public double GetIncoming(DateTime date, int hour = -1)
        {
            if (hour != -1)
            {
                date.AddHours(hour);
            }
            String filter = "Date = '" + date.ToShortDateString() + "'";
            filter += " AND hour = " + (date.Hour + 1);
            System.Data.DataRow[] rows = this.production.Select(filter);

            double incoming = 0;
            if (rows.Length != 0)
            {
                incoming = (double)rows[0]["Incoming"];
            }
            return incoming;
        }
        public double TotalOutgoing(DateTime dateFrom, DateTime dateTo)
        {
            double total = 0;
            while (dateFrom < dateTo)
            {
                total += this.GetOutgoing(dateFrom);
                dateFrom = dateFrom.AddHours(1);
            }
            return total;
        }
        public double TotalIncoming(DateTime dateFrom, DateTime dateTo)
        {
            double total = 0;
            while (dateFrom < dateTo)
            {
                total += this.GetIncoming(dateFrom);
                dateFrom = dateFrom.AddHours(1);
            }
            return total;
        }
        public double GetOutgoing(DateTime date, int hour = -1)
        {
            if (hour != -1)
            {
                date.AddHours(hour);
            }
            String filter = "Date = '" + date.ToShortDateString() + "'";
            filter += " AND hour = " + (date.Hour + 1);
            System.Data.DataRow[] rows = this.production.Select(filter);

            double outgoing = 0;
            if(rows.Length != 0)
            {
                outgoing = (double)rows[0]["Outgoing"];
            }
            return outgoing;
        }
        private DateTime ConvertHourToDate(int year, int hour)
        {
            DateTime date = new DateTime(year, 1, 1);
            date.AddHours(hour);
            return date;
        }
        /// <summary>
        /// Returns the total amount of hours in year
        /// </summary>
        /// <param name="year"></param>
        /// <returns></returns>
        private int TotalHoursInYear(int year)
        {
            int totalHours = 8760;
            if (DateTime.IsLeapYear(year))
            {
                totalHours += 24;
            }
            return totalHours;
        }
    }
}
